package double_pointer;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * @Description 三数之和(双指针+去重)
 * @Author Firenut
 * @Date 2023-02-14 21:49
 */
public class T15_threeSum {
    //    时间复杂度: O(n^2)
    //    空间复杂度: O(1)
    public List<List<Integer>> threeSum(int[] nums) {
        List<List<Integer>> ans = new ArrayList<>();
        int i, j, k;
        Arrays.sort(nums);
        for (k = 0; k < nums.length - 2; k++) { // ***
            int sum;
            if (nums[k] > 0) {
                break;
            }
            if (k >= 1 && nums[k] == nums[k - 1]) {
                continue;
            }
            i = k + 1;
            j = nums.length - 1;
            while (i < j) {
                sum = nums[k] + nums[i] + nums[j];
                if (sum < 0) {
                    // 如果nums[i]==nums[i+1],需要++i,避免求重复解
                    while (i < j && nums[i] == nums[++i]) ;
                    // 当nums[i]!=nums[++i]就会退出循环,此时i指向的元素刚好是和前面是不相等的元素

                    // 等价于:
//                    if(sum < 0){
//                        i++;
//                        while(i<j&&nums[i] == nums[i-1]){
//                            i++;
//                        }
//                    }
                } else if (sum > 0) {
                    //如果nums[j]==nums[j-1],需要--j,避免求重复解
                    while (i < j && nums[j] == nums[--j]) ;
                } else {
                    ans.add(new ArrayList<>(Arrays.asList(nums[k], nums[i], nums[j])));
                    while (i < j && nums[i] == nums[++i]) ;
                    while (i < j && nums[j] == nums[--j]) ;
                }
            }
        }
        return ans;
    }
}